use std::{fs, io};
use std::fmt::Debug;
use std::fs::Permissions;
use std::io::{Read, Seek};
use std::os::unix::fs::PermissionsExt;
use std::path::PathBuf;

use crate::runtime::error::MagicBoxError;
use crate::runtime::os;
use crate::runtime::response::Code;
use crate::runtime::result::MagicBoxResult;
use crate::state;

/// 获取数据路径
pub(crate) fn data_path(path: PathBuf) -> MagicBoxResult<PathBuf> {
    let data_path = state::application::app().path_resolver().app_data_dir();
    if data_path.is_none() {
        return Err(MagicBoxError::new(Code::IoError, "无法获取应用数据目录"));
    }

    Ok(data_path.unwrap().join(path))
}

/// 解压zip文件
pub(crate) fn unzip_file(path: PathBuf, reader: impl Debug + Read + Seek) -> MagicBoxResult<()> {
    let zip = zip::ZipArchive::new(reader);
    if zip.is_err() {
        return Err(MagicBoxError::new(Code::IoError, format!("解压ZIP文件失败: {}", zip.unwrap_err().to_string()).as_str()));
    }

    let mut zip = zip.unwrap();
    for index in 0..zip.len() {
        let mut file = zip.by_index(index).unwrap();

        if file.is_dir() {
            let result = fs::create_dir_all(path.join(file.name()));
            if result.is_err() {
                return Err(MagicBoxError::new(Code::IoError, format!("创建目录失败: {}", result.unwrap_err().to_string()).as_str()));
            }

            continue;
        }

        let target = fs::File::create(path.join(file.name()));
        if target.is_err() {
            return Err(MagicBoxError::new(Code::IoError, format!("创建文件失败: {}", target.unwrap_err().to_string()).as_str()));
        }

        let mut target = target.unwrap();

        if "Windows" != os::SYSTEM {
            let result = target.set_permissions(Permissions::from_mode(file.unix_mode().unwrap()));
            if result.is_err() {
                return Err(MagicBoxError::new(Code::IoError, format!("设置文件权限失败: {}", result.unwrap_err().to_string()).as_str()));
            }
        }

        let result = io::copy(&mut file, &mut target);
        if result.is_err() {
            return Err(MagicBoxError::new(Code::IoError, format!("写入文件失败: {}", result.unwrap_err().to_string()).as_str()));
        }
    }

    Ok(())
}